package com.canaan.business.controller.pc.inOutStock;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.lang.Pair;
import cn.hutool.json.JSONUtil;
import com.canaan.business.common.enums.inOutStock.BindTypeEnum;
import com.canaan.business.common.enums.inOutStock.ErpBillTypeEnum;
import com.canaan.business.common.enums.inOutStock.InOrderStatusEnum;
import com.canaan.business.domain.bill.*;
import com.canaan.business.domain.inOutStock.*;
import com.canaan.business.domain.vo.GoodsVo;
import com.canaan.business.domain.vo.InStockCallbackVo;
import com.canaan.business.domain.vo.InStockPutWayVo;
import com.canaan.business.service.bill.*;
import com.canaan.business.service.inOutStock.*;
import com.canaan.common.core.redis.RedisCache;
import com.canaan.common.encrypt.PushEdiService;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.system.service.ISysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.canaan.common.annotation.Log;
import com.canaan.common.core.controller.BaseController;
import com.canaan.common.core.domain.AjaxResult;
import com.canaan.common.enums.BusinessType;

import javax.annotation.Resource;

import com.canaan.common.utils.poi.ExcelUtil;
import com.canaan.common.core.page.TableDataInfo;

/**
 * 绑定关系Controller
 *
 * @author canaan
 */
@Api(tags = "绑定关系")
@RestController
@RequestMapping("/inOutStock/bindRecord")
public class BindRecordController extends BaseController {
    /**
     * 采购单前缀
     **/
    private final String Pre_Receive = "DIPI";
    /**
     * 调拨入库单前缀
     **/
    private final String Pre_Adjust_in = "DITRS";
    @Resource
    private IBindRecordService bindRecordService;
    @Resource
    private RedisCache redisCache;

    @Resource
    private IBillDetailRecordService billDetailRecordService;

    @Resource
    private IReceiveProductBillService receiveProductBillService;
    @Resource
    private IReceiveProductBillDetailService receiveProductBillDetailService;
    @Resource
    private IAdjustInBillService adjustInBillService;
    @Resource
    private IModulationInBillService modulationInBillService;
    @Resource
    private ISysConfigService sysConfigService;
    @Resource
    private ITrayService trayService;

    /**
     * 查询绑定关系列表
     */
    @ApiOperation(value = "查询绑定关系列表")
    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:list')")
    @GetMapping("/list")
    public TableDataInfo list(BindRecord bindRecord) {
        startPage();
        List<BindRecord> list = bindRecordService.selectBindRecordList(bindRecord);
        return getDataTable(list);
    }

    /**
     * 导出绑定关系列表
     */
    @ApiOperation(value = "导出绑定关系列表")
    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:export')")
    @Log(title = "绑定关系", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BindRecord bindRecord) {
        List<BindRecord> list = bindRecordService.selectBindRecordList(bindRecord);
        ExcelUtil<BindRecord> util = new ExcelUtil<BindRecord>(BindRecord.class);
        util.exportExcel(response, list, "绑定关系数据");
    }

    /**
     * 获取绑定关系详细信息
     */
    @ApiOperation(value = "获取绑定关系详细信息")
    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:query')")
    @GetMapping(value = "/{parentNo}")
    public AjaxResult getInfo(@PathVariable("parentNo") String parentNo) {
        return success(bindRecordService.selectBindRecordByParentNo(parentNo));
    }

    /**
     * 新增绑定关系
     */
    @ApiOperation(value = "新增绑定关系")
    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:add')")
    @Log(title = "绑定关系", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody BindRecord bindRecord) {
        return toAjax(bindRecordService.insertBindRecord(bindRecord));
    }

    /**
     * 修改绑定关系
     */
    @ApiOperation(value = "修改绑定关系")
    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:edit')")
    @Log(title = "绑定关系", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody BindRecord bindRecord) {
        return toAjax(bindRecordService.updateBindRecord(bindRecord));
    }

    /**
     * 删除绑定关系
     */
    @ApiOperation(value = "删除绑定关系")
    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:remove')")
    @Log(title = "绑定关系", businessType = BusinessType.DELETE)
    @DeleteMapping("/{parentNos}")
    public AjaxResult remove(@PathVariable String[] parentNos) {
        return toAjax(bindRecordService.deleteBindRecordByParentNos(parentNos));
    }

    /**
     * 新增绑定关系
     */
    @ApiOperation(value = "新增绑定关系")
//    @PreAuthorize("@ss.hasPermi('inOutStock:bindRecord:add')")
    @Log(title = "绑定关系", businessType = BusinessType.INSERT)
    @PostMapping("/putWay")
    public synchronized AjaxResult putWay(@RequestBody InStockPutWayVo inStockPutWayVo) {
        logger.info("开始绑定：{}", inStockPutWayVo.toString());
        if (StringUtils.isEmpty(inStockPutWayVo.getBinNo())) {
            return error("库位不能为空");
        } else if (!StringUtils.contains(inStockPutWayVo.getBinNo(), "K")) {
            return error("库位不正确");
        }
        if (StringUtils.isEmpty(inStockPutWayVo.getShelfNo())) {
            return error("料架号不能为空");
        } else if (!StringUtils.startsWith(inStockPutWayVo.getShelfNo(), "H")) {
            return error("料架号不正确");
        }
        if (StringUtils.isEmpty(inStockPutWayVo.getTrayNo())) {
            return error("托盘号不能为空");
        } else if (!StringUtils.startsWith(inStockPutWayVo.getTrayNo(), "T")) {
            return error("托盘号不正确");
        }
        if (inStockPutWayVo.getBillType() == null){
            return error("单据类型不能为空");
        }
        BindRecord shelfQuery = new BindRecord();
        shelfQuery.setBindType((long) BindTypeEnum.SHELF_TRAY.getCode());
        shelfQuery.setParentNo(inStockPutWayVo.getShelfNo());
        shelfQuery.setDelFlag("0");
        List<BindRecord> shelfRecordList = bindRecordService.selectBindRecordList(shelfQuery);
        if (shelfRecordList != null && shelfRecordList.size() != 0) {
            BindRecord bindRecord=shelfRecordList.get(0);
            if(!inStockPutWayVo.getShelfNo().equals(bindRecord.getParentNo())) {
                return error(inStockPutWayVo.getShelfNo() + "已经存在绑定数据");
            }
        }

        BindRecord trayQuery = new BindRecord();
        trayQuery.setBindType((long) BindTypeEnum.SHELF_TRAY.getCode());
        trayQuery.setChildNo(inStockPutWayVo.getTrayNo());
        trayQuery.setDelFlag("0");
        List<BindRecord> trayRecordList = bindRecordService.selectBindRecordList(trayQuery);
        if (trayRecordList != null && trayRecordList.size() != 0) {
            return error(inStockPutWayVo.getTrayNo() + "已经存在绑定数据");
        }

        Tray tray = trayService.selectTrayByTrayNo(inStockPutWayVo.getTrayNo());
        if (tray == null) {
            return error("托盘" + inStockPutWayVo.getTrayNo() + "不存在");
        }
        if (StringUtils.isEmpty(tray.getErpInBillNo())) {
            return error("托盘" + inStockPutWayVo.getTrayNo() + "不存在ERP单据");
        }
        if (ErpBillTypeEnum.RECEIVE_PRODUCT.getCode().equals(inStockPutWayVo.getBillType())) {
            ReceiveProductBill receiveProductBill = receiveProductBillService.selectReceiveProductBillByNo(tray.getErpInBillNo());
            if (receiveProductBill == null) {
                return error("托盘" + inStockPutWayVo.getTrayNo() + "采购入库单不存在");
            }
        } else if (ErpBillTypeEnum.ADJUST_IN.getCode().equals(inStockPutWayVo.getBillType())) {
            AdjustInBill adjustInBill = adjustInBillService.selectAdjustInBillByNo(tray.getErpInBillNo());
            if (adjustInBill == null) {
                return error("托盘" + inStockPutWayVo.getTrayNo() + "调拨入库单不存在");
            }
        } else if (ErpBillTypeEnum.MODULATION_IN.getCode().equals(inStockPutWayVo.getBillType())) {
            ModulationInBill modulationInBill = modulationInBillService.selectModulationInBillByNo(tray.getErpInBillNo());
            if (modulationInBill == null) {
                return error("托盘" + inStockPutWayVo.getTrayNo() + "入库调整单不存在");
            }
        }
        String key = "IN_LOCK";
        //TODO 临时方案锁，后期处理
        String lock = redisCache.getCacheObject(key);
        if (StringUtils.equals(lock, "true")) {
            throw new RuntimeException("有出库任务正在进行中，请稍后再试");
        }
        redisCache.setCacheObject(key, "true");
        try {
            bindRecordService.bindStoreLocation(inStockPutWayVo);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            //TODO 临时方案
            redisCache.setCacheObject(key, "false");
        }
        logger.info("绑定成功：{}", inStockPutWayVo.toString());
        return toAjax(1);
    }

    /**
     * 处理入库回调
     *
     * @param bindRecord
     */
    private void handleInStockCallback(BindRecord bindRecord) {
        if (bindRecord.getBindType() != (long) BindTypeEnum.SHELF_TRAY.getCode()) {
            return;
        }
        BillDetailRecord billDetailQuery = new BillDetailRecord();
        billDetailQuery.setBillType(ErpBillTypeEnum.RECEIVE_PRODUCT.getCode());
        billDetailQuery.setTrayNo(bindRecord.getChildNo());
        List<BillDetailRecord> billDetailRecords = billDetailRecordService.selectBillDetailRecordList(billDetailQuery);
        if (billDetailRecords == null || billDetailRecords.size() == 0) {
            return;
        }
        BillDetailRecord billDetailRecord = billDetailRecords.get(0);
        ReceiveProductBill receiveProductBill = receiveProductBillService.selectReceiveProductBillByNo(billDetailRecord.getBillNo());
        if (receiveProductBill == null) {
            throw new RuntimeException("托盘" + bindRecord.getChildNo() + "不存在采购入库单");
        }
        if (!receiveProductBill.getStatus().equals(InOrderStatusEnum.ACCOMPLISH.getCode())) {
            throw new RuntimeException("托盘" + bindRecord.getChildNo() + "采购入库单" + receiveProductBill.getNo() + "状态不是完成状态");
        }
        postInStockCallback(receiveProductBill);
    }

    /**
     * 入库回调
     *
     * @param bill 采购入库单
     */
    private void postInStockCallback(ReceiveProductBill bill) {
        InStockCallbackVo inStockCallbackVo = new InStockCallbackVo();
        inStockCallbackVo.setBizNo(bill.getNo());
        inStockCallbackVo.setWmsBizNo(bill.getNo());
        ReceiveProductBillDetail query = new ReceiveProductBillDetail();
        query.setBillNo(bill.getNo());
        List<ReceiveProductBillDetail> details = receiveProductBillDetailService.selectReceiveProductBillDetailList(query);
        List<GoodsVo> goodsVos = new ArrayList<>();
        for (ReceiveProductBillDetail item : details) {
            GoodsVo goodsVo = new GoodsVo();
            goodsVo.setBatchNo(item.getBatchNo());
            goodsVo.setCode(item.getProductNo());
            goodsVo.setUnit(item.getProductUnit());
            goodsVo.setNum(item.getQty().toString());
            goodsVo.setStatus(Integer.parseInt(bill.getStockStatus()));
            goodsVos.add(goodsVo);
        }
        inStockCallbackVo.setGoodDetails(goodsVos);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        inStockCallbackVo.setDeliveryDate(simpleDateFormat.format(DateUtils.getNowDate()));
        // 发送回调
        if (Boolean.parseBoolean(sysConfigService.selectConfigByKey("edi.swtich"))) {
            Pair<Boolean, String> result = PushEdiService.push(sysConfigService.selectConfigByKey("edi.inner"), JSONUtil.toJsonStr(inStockCallbackVo));
            System.out.println("post = " + result.getValue());
            if (!result.getKey()) {
                throw new RuntimeException(result.getValue());
            }
        }
    }

}
